package com.lagou.rpc.consumer.proxy;

import com.alibaba.fastjson.JSON;
import com.lagou.ZookeeperCreateNode;
import com.lagou.ZookeeperSelectNode;
import com.lagou.ZookeeperUpdateNode;
import com.lagou.rpc.common.RpcRequest;
import com.lagou.rpc.common.RpcResponse;
import com.lagou.rpc.consumer.client.RpcClient;
import com.lagou.rpc.consumer.request.RequestParams;
import com.lagou.rpc.consumer.util.SpringUtil;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;

/**
 * 客户端代理类-创建代理对象
 * 1.封装request请求对象
 * 2.创建RpcClient对象
 * 3.发送消息
 * 4.返回结果
 */
@Component
public class RpcClientProxy {

//    @Autowired
//    private RpcClient rpcClient;
    @Resource(name = "zookeeper")
    ZooKeeper zooKeeper;


    public Object createProxy(Class serviceClass) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //1.封装request请求对象
                        RpcRequest rpcRequest = new RpcRequest();
                        rpcRequest.setRequestId(UUID.randomUUID().toString());
                        rpcRequest.setClassName(method.getDeclaringClass().getName());
                        rpcRequest.setMethodName(method.getName());
                        rpcRequest.setParameterTypes(method.getParameterTypes());
                        rpcRequest.setParameters(args);
////                        //2.创建RpcClient对象
                        Date date = new Date();
                        RpcClient rpcClient = null;
                        ZookeeperSelectNode zookeeperSelectNode = new ZookeeperSelectNode();
                        ZookeeperCreateNode zookeeperCreateNode = new ZookeeperCreateNode();
                        ZookeeperUpdateNode zookeeperUpdateNode = new ZookeeperUpdateNode();
                        ZooKeeper zooKeeper =(ZooKeeper) SpringUtil.getBean("zookeeper");
                        HashMap<String, String> serviceNodeAndData = zookeeperSelectNode.getServiceNodeAndData(zooKeeper,"/serviceData");
                        String provide = serviceNodeAndData.get("provide");
                        String provide2 = serviceNodeAndData.get("provide2");
                        List<String> ipport = new ArrayList<>();
                        if(provide!=null) {
                            ipport.add(provide);
                        }
                        if(provide2!=null) {
                            ipport.add(provide2);
                        }
                        String value = null;
                        // 先比较请求相应时间,一致或失效则随机取
                        String provideTime = zookeeperSelectNode.getServiceNodeAndDataStr(zooKeeper,"/serviceTime/provide");
                        String provideTime2 = zookeeperSelectNode.getServiceNodeAndDataStr(zooKeeper,"/serviceTime/provide2");
                        RequestParams requestParams1 = JSON.parseObject(provideTime, RequestParams.class);
                        RequestParams requestParams2 = JSON.parseObject(provideTime2, RequestParams.class);
                        Date now = new Date();
                        if(requestParams1!=null && requestParams2!=null && (requestParams1.getRequestDate().getTime()-now.getTime()<5000
                                && requestParams2.getRequestDate().getTime()-now.getTime()<5000 )){
                                if(requestParams1.getRequestTime()-requestParams2.getRequestTime()>0){
                                    value = serviceNodeAndData.get("provide2");
                                }else {
                                    value = serviceNodeAndData.get("provide");
                                }
                        }else {
                            long index = date.getTime() % ipport.size();
                            value = ipport.get((int) index);
                        }

                        String[] split = value.split(":");
                        rpcClient = new RpcClient(split[0], Integer.parseInt(split[1]));


                        try {
                            //3.发送消息
                            long startTime = System.currentTimeMillis();
                            Object responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest));
                            long endTime = System.currentTimeMillis();
                            RequestParams requestParams = new RequestParams();
                            requestParams.setRequestDate(new Date());
                            requestParams.setRequestTime(endTime-startTime);
                            String service = getService(value,serviceNodeAndData);
                            String path = "/serviceTime/"+service;
                            Stat exists = zooKeeper.exists(path, true);

                            if(exists!=null) {
                                zookeeperUpdateNode.updateNode(zooKeeper, JSON.toJSONString(requestParams), path);
                            }else {
                                zookeeperCreateNode.createNode(zooKeeper,JSON.toJSONString(requestParams),path);
                            }
                            RpcResponse rpcResponse = JSON.parseObject(responseMsg.toString(), RpcResponse.class);
                            if (rpcResponse.getError() != null) {
                                System.out.println();
                                throw new RuntimeException(rpcResponse.getError());
                            }
                            //4.返回结果
                            Object result = rpcResponse.getResult();
                            return JSON.parseObject(result.toString(), method.getReturnType());
                        } catch (Exception e) {
                            throw e;
                        } finally {
                            rpcClient.close();
                        }

                    }
                });
    }

    private String getService(String oldvalue, HashMap<String, String> serviceNodeAndData) {
        Set<String> keySet = serviceNodeAndData.keySet();
        Iterator<String> iterator = keySet.iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            String value = serviceNodeAndData.get(next);
            if(oldvalue.equals(value)){
                return next;
            }

        }
        return null;
    }
}
